package com.ailanyin.modules.flowable.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.BetweenFormatter;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.ailanyin.common.base.exception.Assert;
import com.ailanyin.common.database.result.CommonPage;
import com.ailanyin.common.flowable.constant.TaskConstants;
import com.ailanyin.common.flowable.core.FormConf;
import com.ailanyin.common.flowable.factory.FlowServiceFactory;
import com.ailanyin.common.flowable.utils.ModelUtils;
import com.ailanyin.common.flowable.utils.ProcessFormUtils;
import com.ailanyin.common.security.model.LoginUser;
import com.ailanyin.common.security.utils.SecurityUtil;
import com.ailanyin.modules.flowable.domain.bo.WfProcessBo;
import com.ailanyin.modules.flowable.domain.vo.*;
import com.ailanyin.modules.flowable.mapper.UserAndRoleMapper;
import com.ailanyin.modules.flowable.mapper.WfDeployFormMapper;
import com.ailanyin.modules.flowable.service.IWfProcessService;
import com.ailanyin.modules.flowable.service.IWfTaskService;
import org.flowable.bpmn.constants.BpmnXMLConstants;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.StartEvent;
import org.flowable.bpmn.model.UserTask;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.history.HistoricProcessInstanceQuery;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.repository.ProcessDefinitionQuery;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.engine.task.Comment;
import org.flowable.identitylink.api.history.HistoricIdentityLink;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskQuery;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.flowable.task.api.history.HistoricTaskInstanceQuery;
import org.flowable.variable.api.history.HistoricVariableInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author ailanyin
 * @version 1.0
 * @since 2022/12/12 0012 下午 14:48
 */
@Service
public class WfProcessServiceImpl extends FlowServiceFactory implements IWfProcessService {

    @Autowired
    private IWfTaskService wfTaskService;
    @Resource
    private WfDeployFormMapper deployFormMapper;
    @Resource
    private UserAndRoleMapper userAndRoleMapper;

    @Override
    public CommonPage<WfDefinitionVo> processList(Integer pageNum, Integer pageSize) {

        // 流程定义列表数据查询
        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery()
                .active()
                .orderByProcessDefinitionKey()
                .asc();
        long pageTotal = processDefinitionQuery.count();
        if (pageTotal <= 0) {
            return new CommonPage<>(new ArrayList<>(), pageTotal);
        }
        int offset = pageSize * (pageNum - 1);
        List<ProcessDefinition> definitionList = processDefinitionQuery.listPage(offset, pageSize);
        List<WfDefinitionVo> definitionVoList = createWfDefinitionVoList(definitionList);

        return new CommonPage<>(definitionVoList, pageTotal);
    }

    @Override
    public String selectFormContent(String definitionId, String deployId) {
        InputStream inputStream = repositoryService.getProcessModel(definitionId);
        BpmnModel bpmnModel = ModelUtils.getBpmnModel(IoUtil.readUtf8(inputStream));
        StartEvent startEvent = ModelUtils.getStartEvent(bpmnModel);
        return deployFormMapper.selectWfDeployForm(deployId, startEvent.getFormKey(), startEvent.getId()).getContent();
    }

    @Override
    public void startProcess(String procDefId, Map<String, Object> variables) {
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionId(procDefId).singleResult();
        if (Objects.nonNull(processDefinition) && processDefinition.isSuspended()) {
            Assert.fail("流程已被挂起，请先激活流程");
        }
        // 设置流程发起人Id到流程中
        buildProcessVariables(variables);
        ProcessInstance processInstance = runtimeService.startProcessInstanceById(procDefId, variables);
        // 第一个用户任务为发起人，则自动完成任务
        //wfTaskService.startFirstTask(processInstance, variables);
    }

    @Override
    public void startProcessByDefKey(String procDefKey, Map<String, Object> variables) {
        if (StrUtil.isNotBlank(procDefKey)) {
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                    .processDefinitionKey(procDefKey).latestVersion().singleResult();
            if (processDefinition != null && processDefinition.isSuspended()) {
                Assert.fail("流程已被挂起，请先激活流程");
            }
            buildProcessVariables(variables);
            ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(procDefKey, variables);
            wfTaskService.startFirstTask(processInstance, variables);
        }
    }

    @Override
    public String queryBpmnXmlById(String processDefId) {
        return IoUtil.readUtf8(repositoryService.getProcessModel(processDefId));
    }

    @Override
    public WfDetailVo queryProcessDetail(String procInsId, String deployId, String taskId) {
        HistoricTaskInstance taskIns = historyService.createHistoricTaskInstanceQuery()
                .taskId(taskId)
                .includeIdentityLinks()
                .includeProcessVariables()
                .includeTaskLocalVariables()
                .singleResult();

        if (ObjectUtil.isEmpty(taskIns)) {
            Assert.fail("没有可办理的任务！");
        }

        WfDetailVo detailVo = new WfDetailVo();
        InputStream inputStream = repositoryService.getProcessModel(taskIns.getProcessDefinitionId());
        detailVo.setBpmnXml(IoUtil.readUtf8(inputStream));
        detailVo.setTaskFormData(currTaskFormData(deployId, taskIns));
        detailVo.setHistoryProcNodeList(historyProcNodeList(procInsId));
        detailVo.setProcessFormList(processFormList(procInsId, deployId, taskIns));
        detailVo.setFlowViewer(wfTaskService.getFlowViewer(procInsId));
        return detailVo;
    }

    @Override
    public CommonPage<WfTaskVo> queryPageOwnProcessList(Integer pageNum, Integer pageSize) {
        HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery()
                .startedBy(SecurityUtil.getLoginUserId().toString())
                .orderByProcessInstanceStartTime()
                .desc();
        int offset = pageSize * (pageNum - 1);
        List<HistoricProcessInstance> historicProcessInstances = historicProcessInstanceQuery
                .listPage(offset, pageSize);
        long pageTotal = historicProcessInstanceQuery.count();
        List<WfTaskVo> taskVoList = new ArrayList<>();
        for (HistoricProcessInstance hisIns : historicProcessInstances) {
            WfTaskVo taskVo = new WfTaskVo();
            taskVo.setCreateTime(hisIns.getStartTime());
            taskVo.setFinishTime(hisIns.getEndTime());
            taskVo.setProcInsId(hisIns.getId());

            // 计算耗时
            if (Objects.nonNull(hisIns.getEndTime())) {
                taskVo.setDuration(com.ailanyin.common.base.utils.DateUtil.getDatePoor(hisIns.getEndTime(), hisIns.getStartTime()));
            } else {
                taskVo.setDuration(com.ailanyin.common.base.utils.DateUtil.getDatePoor(new Date(), hisIns.getStartTime()));
            }
            // 流程部署实例信息
            Deployment deployment = repositoryService.createDeploymentQuery()
                    .deploymentId(hisIns.getDeploymentId()).singleResult();
            taskVo.setDeployId(hisIns.getDeploymentId());
            taskVo.setProcDefId(hisIns.getProcessDefinitionId());
            taskVo.setProcDefName(hisIns.getProcessDefinitionName());
            taskVo.setProcDefVersion(hisIns.getProcessDefinitionVersion());
            taskVo.setCategory(deployment.getCategory());
            // 当前所处流程
            List<Task> taskList = taskService.createTaskQuery().processInstanceId(hisIns.getId()).list();
            if (CollUtil.isNotEmpty(taskList)) {
                taskVo.setTaskId(taskList.get(0).getId());
            } else {
                List<HistoricTaskInstance> historicTaskInstance = historyService.createHistoricTaskInstanceQuery()
                        .processInstanceId(hisIns.getId()).orderByHistoricTaskInstanceEndTime().desc().list();
                if (CollUtil.isNotEmpty(historicTaskInstance)) {
                    taskVo.setTaskId(historicTaskInstance.get(0).getId());
                }
            }
            taskVoList.add(taskVo);
        }
        return new CommonPage<WfTaskVo>(taskVoList, pageTotal);
    }

    @Override
    public CommonPage<WfTaskVo> queryPageTodoProcessList(Integer pageNum, Integer pageSize) {
        TaskQuery taskQuery = taskService.createTaskQuery()
                .active()
                .includeProcessVariables()
                .taskCandidateOrAssigned(SecurityUtil.getLoginUserId().toString())
                .taskCandidateGroupIn(getCandidateGroup())
                .orderByTaskCreateTime().desc();
        long pageTotal = taskQuery.count();
        int offset = pageSize * (pageNum - 1);
        List<Task> taskList = taskQuery.listPage(offset, pageSize);
        List<WfTaskVo> flowList = new ArrayList<>();
        for (Task task : taskList) {
            flowList.add(createWfTaskVo(task, true));
        }
        return new CommonPage<WfTaskVo>(flowList, pageTotal);
    }

    @Override
    public CommonPage<WfTaskVo> queryPageFinishedProcessList(Integer pageNum, Integer pageSize) {
        HistoricTaskInstanceQuery taskInstanceQuery = historyService.createHistoricTaskInstanceQuery()
                .includeProcessVariables()
                .finished()
                .taskAssignee(SecurityUtil.getLoginUserId().toString())
                .orderByHistoricTaskInstanceEndTime()
                .desc();
        int offset = pageSize * (pageNum - 1);
        List<HistoricTaskInstance> historicTaskInstanceList = taskInstanceQuery.listPage(offset, pageSize);
        List<WfTaskVo> hisTaskList = new ArrayList<>();
        for (HistoricTaskInstance histTask : historicTaskInstanceList) {
            WfTaskVo flowTask = new WfTaskVo();
            // 当前流程信息
            flowTask.setTaskId(histTask.getId());
            // 审批人员信息
            flowTask.setCreateTime(histTask.getCreateTime());
            flowTask.setFinishTime(histTask.getEndTime());
            flowTask.setDuration(DateUtil.formatBetween(histTask.getDurationInMillis(), BetweenFormatter.Level.SECOND));
            flowTask.setProcDefId(histTask.getProcessDefinitionId());
            flowTask.setTaskDefKey(histTask.getTaskDefinitionKey());
            flowTask.setHisProcInsId(histTask.getProcessInstanceId());
            flowTask.setTaskName(histTask.getName());
            setWfTaskVo(flowTask, histTask.getProcessDefinitionId(), histTask.getProcessInstanceId());

            // 流程变量
            flowTask.setProcVars(this.getProcessVariables(histTask.getId()));

            hisTaskList.add(flowTask);
        }

        return new CommonPage<WfTaskVo>(hisTaskList, taskInstanceQuery.count());
    }

    private void setWfTaskVo(WfTaskVo flowTask, String processDefinitionId, String processInstanceId) {
        // 流程定义信息
        ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
                .processDefinitionId(processDefinitionId)
                .singleResult();
        flowTask.setDeployId(pd.getDeploymentId());
        flowTask.setProcDefName(pd.getName());
        flowTask.setProcDefVersion(pd.getVersion());
        flowTask.setProcInsId(processInstanceId);

        // 流程发起人信息
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
                .processInstanceId(processInstanceId)
                .singleResult();
        Map startUser = userAndRoleMapper.selectUserById(Long.parseLong(historicProcessInstance.getStartUserId()));
        flowTask.setStartUserId(startUser.get("userId").toString());
        flowTask.setStartUserName(startUser.get("nickName").toString());
        flowTask.setStartDeptName(startUser.get("deptName").toString());
    }


    @Override
    public CommonPage<WfTaskVo> queryPageClaimProcessList(WfProcessBo processBo, Integer pageNum, Integer pageSize) {

        TaskQuery taskQuery = taskService.createTaskQuery()
                .active()
                .includeProcessVariables()
                .taskCandidateUser(SecurityUtil.getLoginUserId().toString())
                .taskCandidateGroupIn(getCandidateGroup())
                .orderByTaskCreateTime().desc();
        if (StrUtil.isNotBlank(processBo.getProcessName())) {
            taskQuery.processDefinitionNameLike("%" + processBo.getProcessName() + "%");
        }
        long pageTotal = taskQuery.count();
        int offset = pageSize * (pageNum - 1);
        List<Task> taskList = taskQuery.listPage(offset, pageSize);
        List<WfTaskVo> flowList = new ArrayList<>();
        for (Task task : taskList) {
            flowList.add(createWfTaskVo(task, false));
        }
        return new CommonPage<WfTaskVo>(flowList, pageTotal);
    }

    private List<WfDefinitionVo> createWfDefinitionVoList(List<ProcessDefinition> definitionList) {
        List<WfDefinitionVo> definitionVoList = new ArrayList<>();
        for (ProcessDefinition processDefinition : definitionList) {
            String deploymentId = processDefinition.getDeploymentId();
            Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(deploymentId).singleResult();
            WfDefinitionVo vo = new WfDefinitionVo();
            vo.setDefinitionId(processDefinition.getId());
            vo.setProcessKey(processDefinition.getKey());
            vo.setProcessName(processDefinition.getName());
            vo.setVersion(processDefinition.getVersion());
            vo.setDeploymentId(processDefinition.getDeploymentId());
            vo.setSuspended(processDefinition.isSuspended());
            // 流程定义时间
            vo.setCategory(deployment.getCategory());
            vo.setDeploymentTime(deployment.getDeploymentTime());
            definitionVoList.add(vo);
        }

        return definitionVoList;
    }

    /**
     * 扩展参数构建
     *
     * @param variables 扩展参数
     */
    private void buildProcessVariables(Map<String, Object> variables) {
        Long userId = SecurityUtil.getLoginUserId();
        String userIdStr = userId.toString();
        identityService.setAuthenticatedUserId(userIdStr);
        // 流程发起人
        variables.put(BpmnXMLConstants.ATTRIBUTE_EVENT_START_INITIATOR, userIdStr);
        // 流程发起人的直系领导/顶头上司
        variables.put(TaskConstants.IMMEDIATE_SUPERVISOR, userAndRoleMapper.selectDeptLeaderIdByUserId(userId).toString());
    }

    /**
     * 获取当前任务流程表单信息
     */
    private FormConf currTaskFormData(String deployId, HistoricTaskInstance taskIns) {
        WfDeployFormVo deployFormVo = deployFormMapper.selectWfDeployForm(deployId, taskIns.getFormKey(), taskIns.getTaskDefinitionKey());
        if (ObjectUtil.isNotEmpty(deployFormVo)) {
            FormConf currTaskFormData = JSONUtil.toBean(deployFormVo.getContent(), FormConf.class);
            if (null != currTaskFormData) {
                currTaskFormData.setFormBtns(false);
                ProcessFormUtils.fillFormData(currTaskFormData, taskIns.getTaskLocalVariables());
                return currTaskFormData;
            }
        }
        return null;
    }

    /**
     * 获取流程表单信息（不包括当前任务节点）
     */
    private List<FormConf> processFormList(String procInsId, String deployId, HistoricTaskInstance taskIns) {
        List<FormConf> procFormList = new ArrayList<>();
        HistoricProcessInstance historicProcIns = historyService.createHistoricProcessInstanceQuery().processInstanceId(procInsId).includeProcessVariables().singleResult();
        Process process = repositoryService.getBpmnModel(historicProcIns.getProcessDefinitionId()).getMainProcess();

        buildStartFormData(historicProcIns, process, deployId, procFormList);
        buildUserTaskFormData(procInsId, deployId, process, procFormList);
        return procFormList;
    }

    private void buildStartFormData(HistoricProcessInstance historicProcIns, Process process, String deployId, List<FormConf> procFormList) {
        procFormList = procFormList == null ? new ArrayList<>() : procFormList;
        HistoricActivityInstance startInstance = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(historicProcIns.getId())
                .activityId(historicProcIns.getStartActivityId())
                .singleResult();
        StartEvent startEvent = (StartEvent) process.getFlowElement(startInstance.getActivityId());
        WfDeployFormVo startFormInfo = deployFormMapper.selectWfDeployForm(deployId, startEvent.getFormKey(), startEvent.getId());
        if (ObjectUtil.isNotNull(startFormInfo)) {
            FormConf formConf = JSONUtil.toBean(startFormInfo.getContent(), FormConf.class);
            if (null != formConf) {
                formConf.setTitle(startEvent.getName());
                formConf.setDisabled(true);
                formConf.setFormBtns(false);
                ProcessFormUtils.fillFormData(formConf, historicProcIns.getProcessVariables());
                procFormList.add(formConf);
            }
        }
    }

    private void buildUserTaskFormData(String procInsId, String deployId, Process process, List<FormConf> procFormList) {
        procFormList = procFormList == null ? new ArrayList<>() : procFormList;
        List<HistoricActivityInstance> activityInstanceList = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(procInsId).finished()
                .activityType(BpmnXMLConstants.ELEMENT_TASK_USER)
                .orderByHistoricActivityInstanceStartTime().asc()
                .list();
        for (HistoricActivityInstance instanceItem : activityInstanceList) {
            UserTask userTask = (UserTask) process.getFlowElement(instanceItem.getActivityId(), true);
            String formKey = userTask.getFormKey();
            if (formKey == null) {
                continue;
            }
            // 查询任务节点参数，并转换成Map
            Map<String, Object> variables = historyService.createHistoricVariableInstanceQuery()
                    .processInstanceId(procInsId)
                    .taskId(instanceItem.getTaskId())
                    .list()
                    .stream()
                    .collect(Collectors.toMap(HistoricVariableInstance::getVariableName, HistoricVariableInstance::getValue));
            WfDeployFormVo deployFormVo = deployFormMapper.selectWfDeployForm(deployId, formKey, userTask.getId());
            if (ObjectUtil.isNotNull(deployFormVo)) {
                FormConf formConf = JSONUtil.toBean(deployFormVo.getContent(), FormConf.class);
                if (null != formConf) {
                    formConf.setTitle(userTask.getName());
                    formConf.setDisabled(true);
                    formConf.setFormBtns(false);
                    ProcessFormUtils.fillFormData(formConf, variables);
                    procFormList.add(formConf);
                }
            }
        }
    }

    /**
     * 获取历史任务信息列表
     */
    private List<WfProcNodeVo> historyProcNodeList(String procInsId) {
        List<HistoricActivityInstance> historicActivityInstanceList = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(procInsId)
                .activityTypes(CollUtil.newHashSet(BpmnXMLConstants.ELEMENT_EVENT_START, BpmnXMLConstants.ELEMENT_EVENT_END, BpmnXMLConstants.ELEMENT_TASK_USER))
                .orderByHistoricActivityInstanceStartTime().desc()
                .orderByHistoricActivityInstanceEndTime().desc()
                .list();
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
                .processInstanceId(procInsId)
                .singleResult();
        List<Comment> commentList = taskService.getProcessInstanceComments(procInsId);
        List<WfProcNodeVo> elementVoList = new ArrayList<>();
        for (HistoricActivityInstance activityInstance : historicActivityInstanceList) {
            WfProcNodeVo elementVo = new WfProcNodeVo();
            elementVo.setProcDefId(activityInstance.getProcessDefinitionId());
            elementVo.setActivityId(activityInstance.getActivityId());
            elementVo.setActivityName(activityInstance.getActivityName());
            elementVo.setActivityType(activityInstance.getActivityType());
            elementVo.setCreateTime(activityInstance.getStartTime());
            elementVo.setEndTime(activityInstance.getEndTime());
            if (ObjectUtil.isNotNull(activityInstance.getDurationInMillis())) {
                elementVo.setDuration(DateUtil.formatBetween(activityInstance.getDurationInMillis(), BetweenFormatter.Level.SECOND));
            }
            if (BpmnXMLConstants.ELEMENT_EVENT_START.equals(activityInstance.getActivityType())) {
                if (ObjectUtil.isNotNull(historicProcessInstance)) {
                    Long userId = Long.parseLong(historicProcessInstance.getStartUserId());
                    Map user = userAndRoleMapper.selectUserById(userId);
                    if (user != null) {
                        elementVo.setAssigneeId(Long.parseLong(user.get("userId").toString()));
                        elementVo.setAssigneeName(user.get("nickName").toString());
                    }
                }
            } else if (BpmnXMLConstants.ELEMENT_TASK_USER.equals(activityInstance.getActivityType())) {
                if (StrUtil.isNotBlank(activityInstance.getAssignee())) {
                    Map user = userAndRoleMapper.selectUserById(Long.parseLong(activityInstance.getAssignee()));
                    elementVo.setAssigneeId(Long.parseLong(user.get("userId").toString()));
                    elementVo.setAssigneeName(user.get("nickName").toString());
                }
                // 展示审批人员
                List<HistoricIdentityLink> linksForTask = historyService.getHistoricIdentityLinksForTask(activityInstance.getTaskId());
                StringBuilder stringBuilder = new StringBuilder();
                for (HistoricIdentityLink identityLink : linksForTask) {
                    if ("candidate".equals(identityLink.getType())) {
                        if (StrUtil.isNotBlank(identityLink.getUserId())) {
                            Map user = userAndRoleMapper.selectUserById(Long.parseLong(identityLink.getUserId()));
                            stringBuilder.append(user.get("nickName").toString()).append(",");
                        }
                        if (StrUtil.isNotBlank(identityLink.getGroupId())) {
                            if (identityLink.getGroupId().startsWith(TaskConstants.ROLE_GROUP_PREFIX)) {
                                Long roleId = Long.parseLong(StrUtil.strip(identityLink.getGroupId(), TaskConstants.ROLE_GROUP_PREFIX));
                                Map role = userAndRoleMapper.selectRoleById(roleId);
                                stringBuilder.append(role.get("roleName").toString()).append(",");
                            } else if (identityLink.getGroupId().startsWith(TaskConstants.DEPT_GROUP_PREFIX)) {
                                Long deptId = Long.parseLong(StrUtil.strip(identityLink.getGroupId(), TaskConstants.DEPT_GROUP_PREFIX));
                                Map dept = userAndRoleMapper.selectDeptById(deptId);
                                stringBuilder.append(dept.get("deptName").toString()).append(",");
                            }
                        }
                    }
                }
                if (StrUtil.isNotBlank(stringBuilder)) {
                    elementVo.setCandidate(stringBuilder.substring(0, stringBuilder.length() - 1));
                }
                // 获取意见评论内容
                if (CollUtil.isNotEmpty(commentList)) {
                    List<Comment> comments = new ArrayList<>();
                    for (Comment comment : commentList) {

                        if (comment.getTaskId().equals(activityInstance.getTaskId())) {
                            comments.add(comment);
                        }
                    }
                    elementVo.setCommentList(comments);
                }
            }
            elementVoList.add(elementVo);
        }
        return elementVoList;
    }

    private static List<String> getCandidateGroup() {
        List<String> list = new ArrayList<>();
        LoginUser user = SecurityUtil.getLoginUser();
        if (ObjectUtil.isNotNull(user)) {
            if (CollectionUtil.isNotEmpty(user.getRoleIds())) {
                user.getRoleIds().forEach(role -> list.add(TaskConstants.ROLE_GROUP_PREFIX + role));
            }
            if (ObjectUtil.isNotNull(user.getDeptId())) {
                list.add(TaskConstants.DEPT_GROUP_PREFIX + user.getDeptId());
            }
        }
        return list;
    }

    /**
     * 获取流程变量
     *
     * @param taskId 任务ID
     * @return 流程变量
     */
    private Map<String, Object> getProcessVariables(String taskId) {
        HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery()
                .includeProcessVariables()
                .finished()
                .taskId(taskId)
                .singleResult();
        if (Objects.nonNull(historicTaskInstance)) {
            return historicTaskInstance.getProcessVariables();
        }
        return taskService.getVariables(taskId);
    }

    private WfTaskVo createWfTaskVo(Task task, boolean setProcVars) {
        WfTaskVo flowTask = new WfTaskVo();
        // 当前流程信息
        flowTask.setTaskId(task.getId());
        flowTask.setTaskDefKey(task.getTaskDefinitionKey());
        flowTask.setCreateTime(task.getCreateTime());
        flowTask.setProcDefId(task.getProcessDefinitionId());
        flowTask.setTaskName(task.getName());
        // 流程定义信息
        setWfTaskVo(flowTask, task.getProcessDefinitionId(), task.getProcessInstanceId());

        if (setProcVars) {
            // 流程变量
            flowTask.setProcVars(getProcessVariables(task.getId()));
        }
        return flowTask;
    }
}
